import yaml from "js-yaml";
// import json2yaml from "json2yaml";

export const objectToYaml = (obj: any) => {
  return yaml.dump(obj);
};
export const yamlToObject = (yamlStr: string) => {
  return yaml.load(yamlStr);
};

export const objectToList = (
  obj: any,
  kProp = "key",
  vProp = "value"
): { [key: string]: any }[] => {
  if (!obj) return [];
  return Object.keys(obj).map(key => {
    return { [kProp]: key, [vProp]: obj[key] };
  });
};

export const mergeListToObject = (
  list: any[],
  kProp = "key",
  vProp = "value"
): Record<string, any> => {
  return list.reduce((acc, item) => {
    acc[item[kProp]] = item[vProp];
    return acc;
  }, {});
};

export const objectToString = (obj?: any, joiner = ",") => {
  if (!obj) return "";
  return Object.keys(obj)
    .map(key => {
      if (!obj[key]) return "";
      return `${key}=${obj[key]}`;
    })
    .filter(v => v !== "")
    .join(joiner);
};

export const fieldSelectorStr = (obj?: any) => {
  return objectToString(obj, ",");
};

export const getObjectFromKey = (obj: any, key: string): any => {
  const keys = key.split(".");
  if (!obj || keys.length === 0) return undefined;
  let current = obj;
  for (const k of keys) {
    if (Object.keys(current).includes(k)) {
      current = current[k];
    } else {
      return undefined;
    }
  }
  return current;
};

export const setObjectFromKey = (obj: any, key: string, value: any): any => {
  const keys = key.split(".");
  return setObjectFromKeys(obj, keys, value);
};

export const setObjectFromKeys = (
  obj: any,
  keys: string[],
  value: any
): any => {
  if (!obj || keys.length === 0) return undefined;
  let current = obj;
  for (let i = 0; i < keys.length; i++) {
    const k = keys[i];

    if (i === keys.length - 1) {
      current[k] = value;
    } else if (Object.keys(current).includes(k)) {
      current = current[k];
    } else {
      current[k] = {};
      current = current[k];
    }
  }
};

export const createLazyObject = <T extends object>(loaderMap: any) => {
  return new Proxy({} as T, {
    get(target, prop) {
      if (prop in target) {
        return target[prop];
      }

      if (prop in loaderMap) {
        const value = loaderMap[prop]();
        target[prop] = value; // 缓存结果
        return value;
      }

      return undefined;
    }
  });
};

export const createAsyncLazyObject = loaderMap => {
  return new Proxy(
    {},
    {
      get(target, prop) {
        if (prop in target) {
          return target[prop];
        }

        if (prop in loaderMap) {
          const promise = Promise.resolve(loaderMap[prop]());
          target[prop] = promise;
          return promise;
        }

        return undefined;
      }
    }
  );
};

export const isNotEmpty = (target?: any, trim?: boolean): boolean => {
  if (!target) return false;
  switch (typeof target) {
    case "string":
      if (trim) return target.trim() !== "";
      return target !== "";
    case "object":
      if (target[""]) {
        delete target[""];
      }
      return Object.keys(target).length > 0;
    default:
      return true;
  }
};
